
/* {{ FNameTag }} FSM(Finite State Machine，有限状态机) Source File  */
#include "{{ FNameTag | lower }}_fsm.h"


#include <string.h>
#include <stdio.h>
#include <stdlib.h>


//===========================================================
//                 FSM State execution
//===========================================================

#define LOG_I(...) printf(__VA_ARGS__)
#define LOG_E(...) printf(__VA_ARGS__)


typedef struct T{{ Target }}FsmExecTag T{{ Target }}FsmExec;
typedef void (*T{{ Target }}FsmExecDoEnter)(T{{ Target }}Fsm *fsm);
typedef void (*T{{ Target }}FsmExecDoRunOnce)(T{{ Target }}Fsm *fsm, T{{ Target }}FsmState *next_state);
typedef void (*T{{ Target }}FsmExecDoExit)(T{{ Target }}Fsm *fsm);
struct T{{ Target }}FsmExecTag
{
    const char *            name;
    T{{ Target }}FsmExecDoEnter      do_enter;
    T{{ Target }}FsmExecDoRunOnce    do_runonce;
    T{{ Target }}FsmExecDoExit       do_exit;
};


// 切换执行状态, 只能在 T{{ Target }}FsmExec.do_runonce() 中使用
#define CHANGE_FSM_STATE(state)     *next_state = state

//-------------------------------------------------------------

{% for state in StateDef -%}
/***********************************************
 * @eid:    {{ state.eid }} - k{{ Target }}FsmState{{ state.name }}
 * @name:   {{ state.name }}
 * @brief:  {{ state.brief }}
 ***********************************************/

static void T{{ Target }}FsmExecOnState{{ state.name }}DoEnter(T{{ Target }}Fsm *fsm)
{
    // todo
}

static void T{{ Target }}FsmExecOnState{{ state.name }}DoRunOnce(T{{ Target }}Fsm *fsm, T{{ Target }}FsmState *next_state)
{
    // todo 
    CHANGE_FSM_STATE(k{{ Target }}FsmState{{ state.name }})
}

static void T{{ Target }}FsmExecOnState{{ state.name }}DoExit(T{{ Target }}Fsm *fsm)
{
    // todo
}

{% endfor %}


static const T{{ Target }}FsmExec g_{{ Target | lower }}_fsm_exec_table[T{{ Target }}FsmStateMax] =
{
{%- for state in StateDef %}
    /// @eid: {{ state.eid }}  @brief: {{ state.brief }}
    {.name = "{{ state.name }}", .do_enter = T{{ Target }}FsmExecOnState{{ state.name }}DoEnter, .do_runonce = T{{ Target }}FsmExecOnState{{ state.name }}DoRunOnce, .do_exit = T{{ Target }}FsmExecOnState{{ state.name }}DoExit,},
{%- endfor %}
};


//===========================================================
//             {{ Target }} Fsm Private interface
//===========================================================


static void T{{ Target }}FsmExecCurrStateChgNotify(T{{ Target }}Fsm *fsm, T{{ Target }}FsmState form_state, T{{ Target }}FsmState to_state)
{
    LOG_I("State changed from %s[%d] to %s[%d]\n", g_{{ Target | lower }}_fsm_exec_table[form_state].name, form_state, g_{{ Target | lower }}_fsm_exec_table[to_state].name, to_state);
    // todo
}


//===========================================================
//             {{ Target }} Fsm Public interface
//===========================================================


void T{{ Target }}FsmCreate(T{{ Target }}Fsm *fsm, void *user_param)
{
    memset(fsm, 0, sizeof(T{{ Target }}Fsm));
    fsm->user_param = user_param;
    // Initialize the FSM state
}

void T{{ Target }}FsmDestroy(T{{ Target }}Fsm *fsm)
{
    // Cleanup if needed
    fsm->user_param = NULL;
}

void T{{ Target }}FsmInit(T{{ Target }}Fsm *fsm)
{
    // Initialize the FSM state

    g_{{ Target | lower }}_fsm_exec_table[fsm->curr_state].do_enter(fsm);
}

void T{{ Target }}FsmDone(T{{ Target }}Fsm *fsm)
{
    g_{{ Target | lower }}_fsm_exec_table[fsm->curr_state].do_exit(fsm);
}

void T{{ Target }}FsmRunOnce(T{{ Target }}Fsm *fsm)
{
    if ((unsigned)fsm->curr_state < T{{ Target }}FsmStateMax)
    {
        g_{{ Target | lower }}_fsm_exec_table[fsm->curr_state].do_runonce(fsm, &fsm->next_state);

        if (fsm->next_state != fsm->curr_state)
        {
            g_{{ Target | lower }}_fsm_exec_table[fsm->curr_state].do_exit(fsm);

            T{{ Target }}FsmExecCurrStateChgNotify(fsm, fsm->curr_state, fsm->next_state);

            fsm->prev_state = fsm->curr_state;
            fsm->curr_state = fsm->next_state;
            g_{{ Target | lower }}_fsm_exec_table[fsm->curr_state].do_enter(fsm);
        }
    }
    else
    {
        LOG_E("{{ Target }} FSM state invalid, please check!");
        T{{ Target }}FsmInit(fsm);
    }

}

const char *{{ Target }}FsmStateName(T{{ Target }}FsmState state)
{
    const char *name = "Invalid";
    if ((unsigned)state < T{{ Target }}FsmStateMax)
        name = g_{{ Target | lower }}_fsm_exec_table[state].name;
    return name;
}
